#!/usr/bin/env python
# encoding: utf-8
'''
@author: Excelsiorly
@license: (C) Copyright 2022, All Rights Reserved.
@contact: excelsiorly@qq.com
@file: 091. 解码方法.py
@time: 2022/2/23 21:59
@desc: https://leetcode-cn.com/problems/decode-ways/
> 一条包含字母 A-Z 的消息通过以下映射进行了 编码 ：
    ```
    'A' -> "1"
    'B' -> "2"
    ...
    'Z' -> "26"
    ```
要 解码 已编码的消息，所有数字必须基于上述映射的方法，反向映射回字母（可能有多种方法）。例如，"11106" 可以映射为：
    - "AAJF" ，将消息分组为 (1 1 10 6)
    - "KJF" ，将消息分组为 (11 10 6)

注意，消息不能分组为  (1 11 06) ，因为 "06" 不能映射为 "F" ，这是由于 "6" 和 "06" 在映射中并不等价。
给你一个只含数字的 非空 字符串 s ，请计算并返回 解码 方法的 总数 。

题目数据保证答案肯定是一个 32 位 的整数。

1. dp
2. Ot(n), Os(n)
'''
class Solution(object):
    def numDecodings(self, s):
        """
        :type s: str
        :rtype: int
        """
        if not s: return 0
        n = len(s)
        dp = [0]*(n+1)
        dp[0] = 1
        for i in range(1, n+1):
            # 当前字母单独做一种解码（注意i在dp与s中索引相差1）
            if not s[i-1]=='0':
                dp[i] += dp[i-1]
            # 若当前字母可以跟前一个数字可以构成一个字幕，就加上dp[i-2]
            if i>1 and not s[i-2]=='0' and 10*int(s[i-2])+int(s[i-1])<=26:
                dp[i] += dp[i-2]
        return dp[n]

if __name__ == '__main__':
    res = Solution().numDecodings("12")
